﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Kkc.Model;
using Kkc.Common;
using Kkc.Application.Specifications;
using System.ServiceModel.Syndication;
using Kkc.Application.Helpers;
using System.Web;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace Kkc.Application.Controllers
{
    [HandleError]
    public class PhotoController: Controller
    {
        public ActionResult Index(int albumId, int? pageIndex, int? pageSize)
        {
            return View();
        }

        public ActionResult List(int albumId, int? pageIndex, int? pageSize)
        {
            var take = pageSize ?? 10;
            var skip = take * pageIndex ?? 0;

            using (var entities = new KkcDataEntities())
            {
                var query = entities.Photos.Where(p => p.Album.Id == albumId).AsQueryable();

                var specification = IocContainer.Current.Resolve<ISpecification<Photo>>("published");
                query = query.Satisfy(specification);

                query = query.OrderByDescending(a => a.CreationDate);

                var list = query.Skip(skip).Take(take).ToList();

                ViewData.Model = list;
            }

            return View();
        }

        public ActionResult Details(int id)
        {
            using (var entities = new KkcDataEntities())
            {
                var query = from a in entities.Photos
                            where a.Id == id
                            select a;

                var album = query.FirstOrDefault();
                ViewData.Model = album;
            }

            return View();
        }

        public ActionResult Random()
        {
            using (var entities = new KkcDataEntities())
            {
                var photoCount = entities.Photos.Count();
                var query = entities.Photos.Include("Album").OrderBy(p => p.CreationDate).Skip(new Random().Next(photoCount));

                var album = query.FirstOrDefault();
                ViewData.Model = album;
            }

            return View();
        }

        [Authorize(Roles = "Contributor")]
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Edit(int id)
        {
            using (var entities = new KkcDataEntities())
            {
                var query = from a in entities.Photos
                            where a.Id == id
                            select a;

                var album = query.FirstOrDefault();
                ViewData.Model = album;
            }

            return View();
        }

        [Authorize(Roles = "Contributor")]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(int id, string title, string summary)
        {
            using (var entities = new KkcDataEntities())
            {
                var query = from a in entities.Photos
                            where a.Id == id
                            select a;

                var album = query.First();
                album.Title = title;
                album.Summary = summary;
                entities.SaveChanges();
            }

            return RedirectToAction("Details", new { Id = id });
        }

        [Authorize(Roles = "Contributor")]
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Create(int albumId)
        {
            using (var entities = new KkcDataEntities())
            {
                var photo = new Photo();
                photo.Album = entities.Albums.First(a => a.Id == albumId);
                ViewData.Model = photo;
            }
            return View();
        }

        [Authorize(Roles = "Contributor")]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(int albumId, string title, string summary, HttpPostedFileBase imageFile)
        {
            using (var entities = new KkcDataEntities())
            {
                var file = new Kkc.Model.File();
                file.Filename = Path.GetFileName(imageFile.FileName);
                file.ContentType = imageFile.ContentType;
                file.ContentLength = imageFile.ContentLength;
                using (var reader = new BinaryReader(imageFile.InputStream))
                {
                    file.Contents = reader.ReadBytes(imageFile.ContentLength);
                }
                var md5 = System.Security.Cryptography.MD5.Create();
                var hash = md5.ComputeHash(file.Contents, 0, file.Contents.Length);

                var checksumBuilder = new StringBuilder();
                foreach (var digit in hash)
                {
                    checksumBuilder.AppendFormat("{0:x2}", digit);
                }
                file.Checksum = checksumBuilder.ToString();
                
                var photo = new Photo();
                photo.Album = entities.Albums.First(a => a.Id == albumId);
                photo.Title = title;
                photo.Summary = summary;
                photo.File = file;
                entities.AddToPhotos(photo);
                entities.SaveChanges();
                entities.Refresh(System.Data.Objects.RefreshMode.StoreWins, photo);
                return RedirectToAction("Details", new { id = photo.Id });
            }
        }

        [OutputCache(CacheProfile = "heavy")]
        public ActionResult Image(int id)
        {
            using (var entities = new KkcDataEntities())
            {
                var fileQuery = from p in entities.Photos
                                where p.Id == id
                                select p.File;

                var file = fileQuery.First();
                return new BinaryResult(file.Contents, file.ContentType);
            }
        }

        [OutputCache(CacheProfile = "heavy")]
        public ActionResult Thumbnail(int id, int? width, int? height)
        {
            using (var entities = new KkcDataEntities())
            {
                var fileQuery = from p in entities.Photos
                                where p.Id == id
                                select p.File;

                var file = fileQuery.First();

                return new BinaryResult(ResizeImage(file.Contents, ImageFormat.Jpeg, new Size(width ?? 160, height ?? 120)), "image/jpeg");
            }
        }
    
        private static byte[] ResizeImage(byte[] imageBuffer, ImageFormat targetFormat, Size targetSize)
        {
            Image imgToResize;
            using (var imageStream = new MemoryStream(imageBuffer))
            {
                imgToResize = Bitmap.FromStream(imageStream);
            }

            var sourceWidth = imgToResize.Width;
            var sourceHeight = imgToResize.Height;

            var nPercentW = ((float)targetSize.Width / (float)sourceWidth);
            var nPercentH = ((float)targetSize.Height / (float)sourceHeight);

            var nPercent = .0;
            if (nPercentH < nPercentW)
                nPercent = nPercentH;
            else
                nPercent = nPercentW;

            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);

            var resizedImage = new Bitmap(destWidth, destHeight);
            using (var graphics = Graphics.FromImage((Image)resizedImage))
            {
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
            }

            using (var resizedStream = new MemoryStream())
            {
                resizedImage.Save(resizedStream, targetFormat);
                return resizedStream.ToArray();
            }
        }
    }
}
